﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Unleashed.AutoUpdate.CustomActions
{
    /// <summary>
    /// This context is sent to rollback methods as a parameter, you can for example log the exception
    /// </summary>
    public class RollbackCustomActionContext
    {
        public CustomActionContext ActionContext { get; set; }
        public Exception Exception { get; set; }
    }

    public class CustomActionContext
    {
        /// <summary>
        /// Version of the application before the update
        /// </summary>
        public Version OriginalVersion { get; set; }

        /// <summary>
        /// Version of the update downloaded from your update site
        /// </summary>
        public Version UpdateVersion { get; set; }

        /// <summary>
        /// Path to the auto update exe files that executes the update
        /// </summary>
        public string UpdateExecutionPath { get; set; }

        /// <summary>
        /// Path to the backup folder (before performing update each file is backed up in case of a failure)
        /// </summary>
        public string BackupTempPath { get; set; }

        /// <summary>
        /// Path of the folder where downloaded files are temporarily extracted (will be deleted when upload is finished)
        /// </summary>
        public string UpdateTempPath { get; set; }
    }

    public abstract class CustomAction
    {
        internal Exception TryPreWriteActions(CustomActionContext context)
        {
            try
            {
                PreWriteActions(context);
            }
            catch (Exception ex)
            {
                return ex;
            }

            return null;
        }

        internal Exception TryPostWriteActions(CustomActionContext context)
        {
            try
            {
                PostWriteActions(context);
            }
            catch (Exception ex)
            {
                return ex;
            }

            return null;
        }

        internal Exception TryRollbackPreWriteActions(RollbackCustomActionContext context)
        {
            try
            {
                RollbackPreWriteActions(context);
            }
            catch (Exception ex)
            {
                return ex;
            }

            return null;
        }

        internal Exception TryRollbackPostWriteActions(RollbackCustomActionContext context)
        {
            try
            {
                RollbackPostWriteActions(context);
            }
            catch (Exception ex)
            {
                return ex;
            }

            return null;
        }

        internal Exception TryCommitUpdate(CustomActionContext context)
        {
            try
            {
                CommitUpdate(context);
            }
            catch (Exception ex)
            {
                return ex;
            }

            return null;
        }

        /// <summary>
        /// This method will be executed before the update provider overwrites files included in update
        /// </summary>
        public abstract void PreWriteActions(CustomActionContext context);

        /// <summary>
        /// This method will be executed after the update provider overwrites files included in update
        /// </summary>
        public abstract void PostWriteActions(CustomActionContext context);

        /// <summary>
        /// If there is an error occured, the rollback is initiated, first post-write rollback is exected,
        /// then files are restored from backup and this method is executed as the last one
        /// </summary>
        public abstract void RollbackPreWriteActions(RollbackCustomActionContext context);

        /// <summary>
        /// If there is an error occured, the rollback is initiated, first post-write rollback is executed (this method),
        /// then files are restored from backup
        /// </summary>
        public abstract void RollbackPostWriteActions(RollbackCustomActionContext context);

        /// <summary>
        /// This method is executed if the update is successful, then the temp files are deleted
        /// </summary>
        public abstract void CommitUpdate(CustomActionContext context);
    }
}